package com.flca.frw.validators;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ListResourceBundle;
import java.util.ResourceBundle;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.flca.frw.util.HashUtil;

public class ValidationError implements Serializable {

	private static final long serialVersionUID = -2149640088854366704L;

	private static Logger log = LoggerFactory.getLogger(ValidationError.class);
	
	public static final String ERROR_MESSAGES_KEY = "error.messages";
	public static final String ERROR_MESSAGES_DEFAULT = "error-messages";
	/*
	 * TODO is this what we want?, what bout several error messages files?
	 * maybe we should replace this to another class like PropertHelper, that gets 
	 * injected at startup time
	 */
	private static ResourceBundle resBundle;
	
	/**
	 * ctor
	 * @param aAttribuutnaam
	 * @param afoutcode
	 * @param aParameters
	 */
	public ValidationError(String aAttribuutnaam, String afoutcode, String[] aParameters) 
	{
		this.propertyName = aAttribuutnaam;
		this.errorCode = afoutcode;
		this.parameters = aParameters;
	}

	/**
	 * ctor
	 * @param aAttribuutnaam
	 * @param afoutcode
	 */
	public ValidationError(String aAttribuutnaam, String afoutcode) {
		this.errorCode = afoutcode;
		propertyName = aAttribuutnaam;
		parameters = null;
	}

	public String getPropertyName() {
		return propertyName;
	}

	public String getErrorCode() {
		return errorCode;
	}

	public String[] getParameters() {
		return parameters;
	}

	void setPropertyName(String aAttribuutnaam) {
		this.propertyName = aAttribuutnaam;
	}

	void setErrorCode(String afoutcode) {
		this.errorCode = afoutcode;
	}

	void setParameters(final String[] parameters) {
		this.parameters = parameters;
	}

	public boolean equals(Object obj) {
		if (obj != null && obj instanceof ValidationError) {
			ValidationError sgn = (ValidationError) obj;
			
			return this.hashCode() == sgn.hashCode();
		} else {
			return false;
		}
	}

	
	@Override
	public int hashCode()
	{
		int result = HashUtil.calcHash(0, getErrorCode());
		result += HashUtil.calcHash(result, getPropertyName());
		result += HashUtil.calcHash(result, getParameters());
		
		return result;
	}

	public void setParameters(Object[] objects) 
	{
		if (objects instanceof String[]) {
			parameters = (String[]) objects;
		}
	}

	private String propertyName;

	private String errorCode;

	private String[] parameters;
	
	public String toString() {
		StringBuffer sb = new StringBuffer("<ValidationError>");
		sb.append("<foutcode>").append(errorCode).append("</foutcode>");
		if (propertyName != null) {
			sb.append("<attribuutnaam>").append(propertyName).append(
					"</attribuutnaam>");
		}
		if (parameters != null) {
			sb.append("<parameters>");
			for (int i = 0; i < parameters.length; i++) {
				if (parameters[i] != null) {
					sb.append("<parameter>").append(parameters[i]).append(
							"</parameter>");
				}
			}
			sb.append("</parameters>");
		}
		sb.append("</ValidationError>");
		return sb.toString();
	}

	public String toFormattedMessage() 
	{
		String msg = null;
		if (this.errorCode != null) {
			try {
				msg = getResourceBundle().getString(this.errorCode);
			} catch (Exception e) {
				msg = this.errorCode;
				log.warn("no error message for: " + this.errorCode);
			}
			MessageFormat formatter = new MessageFormat("");
			formatter.applyPattern(msg);
			
			msg = formatter.format(getParams());
		} else {
			msg = this.propertyName;
		}
		
		return msg;
	}

	private String[] getParams() 
	{
		String result[] = null;
		if (this.parameters != null) {
			result = new String[this.parameters.length + 1];
			result[0] = this.propertyName;
			int i = 1;
			for (String s : this.parameters) {
				result[i++] = s;
			}
		} else {
			result = new String[] {this.propertyName};
		}
		return result;
	}
	
	private ResourceBundle getResourceBundle()
	{
		if (resBundle == null) {
			synchronized (ValidationError.class) {
				String reskey = System.getProperty(ERROR_MESSAGES_KEY);
				if (reskey != null)  {
					resBundle = ResourceBundle.getBundle(reskey);
				} else {
					log.error("No property defined for: " + ERROR_MESSAGES_KEY);
					log.error("using the default " + ERROR_MESSAGES_DEFAULT);
					resBundle = ResourceBundle.getBundle(ERROR_MESSAGES_DEFAULT);
				}
			}
			
			if (resBundle == null) {
				log.error("no error messages found");
				resBundle = new DummyResBundle();
			}
		}
		
		return resBundle;
	}
	
	
	private class DummyResBundle extends ListResourceBundle {

		@Override
		protected Object[][] getContents() {
			return null;
		}
		
	}
}
